package com.iwdnb.gkgz.common.quota;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.google.common.collect.Lists;
import com.iwdnb.gkgz.common.model.dto.StockDayData;
import com.iwdnb.gkgz.common.utils.BigDecimalUtils;
import com.iwdnb.gkgz.common.utils.StockUtils;

/**
 * 首先计算N日内最高价和最低价的波动范围（HN和LN）：
 *
 * HN = MAX(HIGH, N)
 *
 * LN = MIN(LOW, N)
 *
 * 然后计算当日的WR指标：
 *
 * WR = 100 * (HN - CLOSE) / (HN - LN)
 */
public class WRIndicator {
    public static final String QUOTA_NAME = "wr";
    private static final Integer PERIOD = 21;

    public static void calculateWR(List<StockDayData> stockDayDataList) {
        calculateWR(stockDayDataList, PERIOD);
    }

    public static void calculateWR(List<StockDayData> stockDayDataList, int period) {
        List<BigDecimal> list = doCalculateWR(stockDayDataList, period);
        int size = stockDayDataList.size();
        for (int i = 0; i < size; i++) {
            StockDayData stockDayData = stockDayDataList.get(i);
            //Double d = list.get(i);
            //BigDecimal data = BigDecimalUtils.of(d);
            BigDecimal data = list.get(i);
            StockUtils.setStockQuota(stockDayData, QUOTA_NAME, data);
            StockUtils.setStockQuota(stockDayData, QUOTA_NAME + period, data);

        }
    }

    public static List<BigDecimal> doCalculateWR(List<StockDayData> stockDayDataList, int period) {
        List<BigDecimal> wrValues = new ArrayList<>();

        for (int i = 0; i < stockDayDataList.size(); i++) {
            if (i < period - 1) {
                // 若数据不够，则返回0或空值
                wrValues.add(BigDecimalUtils.fifty);
                continue;
            }

            // 获取N日内的最高价和最低价
            BigDecimal highestHigh = BigDecimal.valueOf(Double.MIN_VALUE);
            BigDecimal lowestLow = BigDecimal.valueOf(Double.MAX_VALUE);

            for (int j = i - period + 1; j <= i; j++) {
                StockDayData stockData = stockDayDataList.get(j);
                if (stockData.getMaxPrice().compareTo(highestHigh) > 0) {
                    highestHigh = stockData.getMaxPrice();
                }
                if (stockData.getMinPrice().compareTo(lowestLow) < 0) {
                    lowestLow = stockData.getMinPrice();
                }
            }

            // 当前收盘价
            BigDecimal closePrice = stockDayDataList.get(i).getClosePrice();

            // 计算WR
            BigDecimal v1 = highestHigh.subtract(closePrice);
            BigDecimal v2 = highestHigh.subtract(lowestLow);
            BigDecimal wr = BigDecimalUtils.divideToPrecent(v1, v2);
            wrValues.add(wr);
        }

        return wrValues;
    }

    /**
     * 获取最大WR值
     *
     * @param stockDayDataList
     * @return
     */
    public static BigDecimal getMaxWr(List<StockDayData> stockDayDataList) {
        List<BigDecimal> wrList = stockDayDataList.stream().map(
            t -> (BigDecimal)StockUtils.getStockQuota(t, QUOTA_NAME)).collect(Collectors.toList());
        return wrList.stream().max(BigDecimal::compareTo).orElse(new BigDecimal(0.00));
    }

    /**
     * 获取最小WR值
     *
     * @param stockDayDataList
     * @return
     */
    public static BigDecimal getMinWr(List<StockDayData> stockDayDataList) {
        List<BigDecimal> wrList = stockDayDataList.stream().map(
            t -> (BigDecimal)StockUtils.getStockQuota(t, QUOTA_NAME)).collect(Collectors.toList());
        return wrList.stream().min(BigDecimal::compareTo).orElse(new BigDecimal(0.00));
    }
}